#include <atomic>
#include <array>
#include <thread>
#include <iostream>

// 固定容量无锁环形缓冲区
constexpr size_t kCapacity = 4;
// 总任务数
constexpr int kItems = 10;

// 用数组做环形缓冲
std::array<int, kCapacity> buffer{};

// 写指针，表示下一个生产的位置
std::atomic<size_t> write_pos{0};
// 读指针，表示下一个消费的位置
std::atomic<size_t> read_pos{0};
// 缓冲区当前元素数量
std::atomic<int> count{0};
// 生产者完成状态
std::atomic<bool> done{false};

void producer() {
    for (int i = 0; i < kItems; ++i) {
        // 等待直到缓冲区有空位：当 count == kCapacity 时阻塞
        while (true) {
            int current = count.load(std::memory_order_acquire);
            if (current < kCapacity) {
                // 试图将 count +1 保留名额，避免多个生产者同时写入同一槽位
                if (count.compare_exchange_weak(current, current + 1,
                                                std::memory_order_acq_rel,
                                                std::memory_order_acquire)) {
                    break; // 成功占位，跳出循环
                }
            } else {
                // 缓冲区满，等待消费者消费后唤醒
                count.wait(kCapacity, std::memory_order_relaxed);
            }
        }

        // 有容量后，写入数据
        size_t pos = write_pos.fetch_add(1, std::memory_order_relaxed) % kCapacity;
        buffer[pos] = i;

        // 唤醒可能等待数据的消费者
        count.notify_one();
    }

    // 所有数据写完，设定结束标记并唤醒所有等待线程
    done.store(true, std::memory_order_release);
    count.notify_all();
}

void consumer() {
    int processed = 0;
    while (processed < kItems) {
        // 等待缓冲区有数据
        while (true) {
            int current = count.load(std::memory_order_acquire);
            if (current > 0) {
                break; // 有数据可消费
            }
            if (done.load(std::memory_order_acquire)) {
                return; // 若生产者结束且无数据，提前返回
            }
            count.wait(0, std::memory_order_relaxed); // 等待生产者唤醒
        }

        // 读取元素
        size_t pos = read_pos.fetch_add(1, std::memory_order_relaxed) % kCapacity;
        int item = buffer[pos];
        std::cout << "consume " << item << '\n';
        ++processed;

        // 消费后更新 count，释放槽位
        int previous = count.fetch_sub(1, std::memory_order_acq_rel);
        if (previous == kCapacity) {
            // 若消费前缓冲区满，则唤醒可能等待空位的生产者
            count.notify_one();
        }
    }
}

int main() {
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join();
    t2.join();
}